﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections;
using System.Collections.ObjectModel;
using System.Net;

namespace Faust.Andrew.MTG
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //Web and database objects
        private Gatherer _gatherer;
        private DataStore _dataStore;
        private DragDropManager _dragManager;

        //The currently selected deck.
        //private Deck _currentDeck;
        //private bool _isNewDeck;        

        //The currently listed cards
        private CardSearchParameters _currentSearchParameters;
        private CardSearchResults _currentSearchResults;

        private List<DeckWindow> _openDecks;

        //private DeckWindow _deckWindow;

        public MainWindow()
        {
            InitializeComponent();

            _dragManager = new DragDropManager();
            _openDecks = new List<DeckWindow>();
            string dataDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments) + "\\MTGManager";
            _dataStore = new DataStore(dataDirectory);
            //_dataStore = new DataStore(Properties.Settings.Default.DataFile, Properties.Settings.Default.ImagePath);

            if (_dataStore.IsCurrentVersion == false)
            {
                MessageBox.Show(Faust.Andrew.MTG.Properties.Resources.DbUpgradeSteps);
            }

            _gatherer = new CachedGatherer(_dataStore);
            _gatherer.FindCardsCompleteEvent += Gatherer_FindCardsCompleteEvent;		
        }

        private void CheckVersion()
        {
            System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
            worker.DoWork += new System.ComponentModel.DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

            worker.RunWorkerAsync();
        }

        void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            //e.Result is set to a bool indicating whether or not there is a new version.
            if ((bool)e.Result)
            {
                Title = String.Format("{0} - New Version Available", Title);
                //if (MessageBox.Show("There is a new version available. Would you like to to be taken to the download page?", "New Version", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                //{
                //    System.Diagnostics.Process proc = new System.Diagnostics.Process();
                //    proc.StartInfo.FileName = "http://www.andrewfaust.com/mtg";
                //    proc.Start();
                //}
            }
        }

        void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            e.Result = IsNewVersionAvailable();            
        }

        private bool IsNewVersionAvailable()
        {
            try
            {
                string url = "http://www.andrewfaust.com/storage/mtgfiles/Version.txt";
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                using (System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream()))
                {
                    string latestVersion = reader.ReadToEnd();
                    return IsNewVersionAvailable(latestVersion);
                }
            }
            catch
            {
                return false;
            }
        }

        private bool IsNewVersionAvailable(string latestVersion)
        {
            string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            
            return (currentVersion != latestVersion);
        }

        void Gatherer_FindCardsCompleteEvent(object sender, FindCardsEventArgs e)
        {
            _currentSearchResults = e.Results;
            
            pageControl.SetPages(e.Results.Page, e.Results.Pages, true);

            lbCards.ItemsSource = _currentSearchResults.Cards;
            lblCount.Content = _currentSearchResults.TotalCards;
            if (_currentSearchResults.TotalCards >= 0)
            {
                //We have a count so show it
                countPanel.Visibility = Visibility.Visible;
            }
            else
            {
                //The count is unknown so hide the count result
                countPanel.Visibility = Visibility.Collapsed;
            }

            btnSearch.IsEnabled = true;

            if (e.Results.Cards.Count == 0)
            {
                MessageBox.Show("No Results");
            }
        }

        private void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            btnSearch.IsEnabled = false;
            CardSearchParameters searchParameters = new CardSearchParameters()
            {
                Name = txtName.Text,
                Color = cmbColor.Text,
                Rarity = cmbRarity.Text,
                Type = cmbType.Text,
                Text = txtCardText.Text,
                Owned = chkOwned.IsChecked.Value,
                Expansion = cmbExpansion.Text,
                SubType = cmbSubtype.Text,
                UseGatherer = chkOnline.IsChecked.Value,
                Page = 0,
                CustomWhereClause = txtWhereClause.Text,
                SortOrder = (SortOrder)Enum.Parse(typeof(SortOrder), (cmbSort.SelectedItem as ListBoxItem).Content as string)
            };

            Properties.Settings.Default.UseGatherer = chkOnline.IsChecked.GetValueOrDefault();
            Properties.Settings.Default.SearchOwned = chkOwned.IsChecked.GetValueOrDefault();
            Properties.Settings.Default.Save();    

            _currentSearchParameters = searchParameters;
            _gatherer.FindCardsAsync(searchParameters);
        }

        private void pageControl_PageChangedEvent(object sender, Faust.Andrew.MTG.PageChangedEventArgs e)
        {
            btnSearch.IsEnabled = false;
            _currentSearchParameters.Page = e.Page;
            _gatherer.FindCardsAsync(_currentSearchParameters);
        }

        private void mnuImportCards_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            ImportWindow importWindow = new ImportWindow(_gatherer, _dataStore);
            importWindow.ShowDialog();

            RefreshDecks();
        }

        private void mnuExit_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {

            Application.Current.Shutdown();
        }

        private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            chkOnline.IsChecked = Properties.Settings.Default.UseGatherer;
            chkOwned.IsChecked = Properties.Settings.Default.SearchOwned;
            RefreshDecks();

            CheckVersion();            
        }

        private void RefreshDecks()
        {
            lbDecks.Items.Clear();
            List<string> allDecks = _dataStore.ListDecks();
            allDecks.ForEach(deckName => lbDecks.Items.Add(deckName));
        }

        private void lbDecks_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {            
            
        }

        //private void LoadDeck(string deckName)
        //{

        //    Deck deck = null;

        //    if (_isNewDeck)
        //    {
        //        deck = _currentDeck;
        //    }
        //    else
        //    {
        //        deck = _dataStore.GetDeck(deckName);
        //    }
                

        //    LoadDeck(deck);
        //}

        //private void LoadDeck(Deck deck)
        //{
        //    if (deck == null)
        //        throw new ArgumentNullException("deck", "deck is null.");

        //    ClearSelectedDeck();

        //    _currentDeck = deck;
        //    _currentDeck.IsChanged = false;

        //    //lbDeck.ItemsSource = _currentDeck.Cards;
        //    //ExpanderDeck.Header = String.Format("Deck - {0}", _currentDeck.Name);

        //    //txtDeckName.DataContext = _currentDeck;
        //    //txtDeckDescription.DataContext = _currentDeck;

        //    btnSaveDeck.IsEnabled = true;
        //    btnDeleteDeck.IsEnabled = true;

        //    //deckStatistics.Deck = _currentDeck;

        //    if (_deckWindow == null)
        //    {
        //        _deckWindow = new DeckWindow();
        //        _deckWindow.Show();
        //        _deckWindow.Deck = _currentDeck;
        //    }
        //}

        //private void ClearSelectedDeck()
        //{
        //    _currentDeck = null;

        //    if (_deckWindow != null)
        //    {
        //        _deckWindow.Close();
        //        _deckWindow = null;                
        //    }

        //    //lbDeck.ItemsSource = null;
        //    //lbDeck.Items.Clear();
        //    //ExpanderDeck.Header = "Deck";

        //    btnSaveDeck.IsEnabled = false;
        //    btnDeleteDeck.IsEnabled = false;
        //}

        //private void CheckSaveDeck()
        //{
        //    CheckSaveDeck(false);
        //}

        //private void CheckSaveDeck(bool overridePrompt)
        //{
        //    if (_currentDeck != null)
        //    {
        //        if (overridePrompt || MessageBox.Show(String.Format("Would you like to save your changes to the {0} deck?", _currentDeck.Name), 
        //                "Save Changes?", 
        //                MessageBoxButton.YesNo) == MessageBoxResult.Yes)
        //        {
        //            if (_currentDeck.DeckID < 1)
        //            {
        //                Deck newDeck = _dataStore.CreateDeck(_currentDeck.Name, _currentDeck.Description);
        //                _currentDeck.DeckID = newDeck.DeckID;
                        
        //            }

        //            _dataStore.UpdateDeck(_currentDeck, true);
        //        }
        //    }
        //}

        private void CheckDeleteDeck()
        {
            //if (_currentDeck != null && _currentDeck.DeckID > 0)
            //{
            //    if (MessageBox.Show(String.Format("Are you certain you wish to delete the {0} deck?", _currentDeck.Name),
            //            "Delete Deck?",
            //            MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            //    {
            //        _dataStore.DeleteDeck(_currentDeck);
            //        ClearSelectedDeck();
            //    }
            //}

            string deckName = lbDecks.SelectedItem as string;
            if (!String.IsNullOrEmpty(deckName))
            {
                Deck deck = _dataStore.GetDeck(deckName);
                if (MessageBox.Show(String.Format("Are you certain you wish to delete the {0} deck?", deck.Name),
                        "Delete Deck?",
                        MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    _dataStore.DeleteDeck(deck);
                }
            }
        }


        //private void mnuAddToDeck_Click(object sender, System.Windows.RoutedEventArgs e)
        //{
        //    if (_currentDeck == null) { return; }
        //    if (!(lbCards.SelectedItem is Card)) { return; }

        //    Card card = lbCards.SelectedItem as Card;
        //    _currentDeck.SetCardQuantity(card, 1, true);
        //    if (_deckWindow == null || !_deckWindow.IsLoaded)
        //    {
        //        _deckWindow = new DeckWindow();
        //        _deckWindow.Deck = _currentDeck;
        //        _deckWindow.Show();
        //    }
        //    else
        //    {
                
        //        _deckWindow.Show();
        //        _deckWindow.Refresh();
        //    }

        //    //lbDeck.ItemsSource = null;
        //    //lbDeck.ItemsSource = _currentDeck.Cards;
        //}        

        private void mnuSaveCard_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Card card = lbCards.SelectedItem as Card;
            if (card == null) { return; }

            _dataStore.UpdateCardQuantity(card.MultiverseID, card.Quantity, false);
        }

        private void btnDeleteDeck_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            CheckDeleteDeck();
            RefreshDecks();
        }

        //private void btnSaveDeck_Click(object sender, System.Windows.RoutedEventArgs e)
        //{
        //    CheckSaveDeck();
        //    RefreshDecks();
        //    lbDecks.SelectedItem = _currentDeck.Name;
        //}

        private void btnNewDeck_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            OpenDeck(String.Empty);
            //CheckSaveDeck();
            //RefreshDecks();
            //_currentDeck = new Deck();
            //_currentDeck.Name = String.Format("NewDeck_{0}", System.IO.Path.GetRandomFileName());
            //lbDecks.Items.Add(_currentDeck.Name);

            //_isNewDeck = true;
            //lbDecks.SelectedItem = _currentDeck.Name;            
            //_isNewDeck = false;

            //CheckSaveDeck(true);
        }

        private void cmbSortBy_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            /*Now that we've added pagination, all sorting must be handled by the data source in order for the pagination to 
             * work properly*/
            //if (_currentCards == null) { return; }
            //ListBoxItem item = cmbSortBy.SelectedItem as ListBoxItem;

            //if (item == null || item.Content == null) { return; }

            //string sortBy = item.Content.ToString();
            
            //bool reset = false;
           
            //switch (sortBy)
            //{
            //    case "Name":
            //        _currentCards.Sort(CardHelper.NameComparer);
            //        reset = true;
            //        break;
            //    case "Rarity":
            //        _currentCards.Sort(CardHelper.RarityComparer);
            //        reset = true;
            //        break;
            //    case "Color":
            //        _currentCards.Sort(CardHelper.ColorComparer);
            //        reset = true;
            //        break;
            //    case "Type":
            //        _currentCards.Sort(CardHelper.TypeComparer);
            //        reset = true;
            //        break;
            //    case "Converted Mana Cost":
            //        _currentCards.Sort(CardHelper.CostComparer);
            //        reset = true;
            //        break;
            //    case "Owned":
            //        _currentCards.Sort(CardHelper.OwnedComparer);
            //        reset = true;
            //        break;
            //    default:
            //        break;
            //}

            //if (reset)
            //{
            //    lbCards.ItemsSource = null;
            //    lbCards.ItemsSource = _currentCards;
            //}
        }

        private void mnuPrintDeckChecklist_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            string deckName = lbDecks.SelectedItem as string;
            if (String.IsNullOrEmpty(deckName))
            {
                MessageBox.Show("You must first select a deck to print.");
                return;
            }

            Deck deck = _dataStore.GetDeck(deckName);
        	// TODO: Add event handler implementation here.
            using (ReportPreviewForm reportForm = new ReportPreviewForm(deck.DeckID, _dataStore.ConnectionString))
            {
                reportForm.ShowDialog();
            }
        }

        private void mnuBackup_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
            MessageBox.Show("Select a location to back up the database to. Any files already in the selected folder will be overwritten.");
            sfd.Filter = "Txt Files|*.txt";
            if (sfd.ShowDialog() == true)
            {
                string directory = System.IO.Path.GetDirectoryName(sfd.FileName);
                _dataStore.BackupRepository(directory);

                MessageBox.Show("Backup Complete");
            }
        }

        private void mnuExportDeck_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            string deckName = lbDecks.SelectedItem as string;

            if (String.IsNullOrEmpty(deckName))
            {
                MessageBox.Show("Must first select a deck");
                return;
            }

            Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
            sfd.Filter = "Text Files|*.txt";
            if (sfd.ShowDialog() == true)
            {
                _dataStore.ExportDeck(deckName, sfd.FileName);

                MessageBox.Show("Export Complete");
            }
        }

        private void btnOpen_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            string deckName = lbDecks.SelectedItem as string;
            OpenDeck(deckName);

            //if (!String.IsNullOrEmpty(deckName))
            //{
            //    LoadDeck(deckName);
            //}

        }

        private void OpenDeck(string deckName)
        {
            DeckWindow deckWindow = _openDecks.SingleOrDefault(window => window.DeckName == deckName);
            if (deckWindow != null)
            {
                deckWindow.Activate();
            }
            else
            {
                deckWindow = new DeckWindow(deckName, (Gatherer)this._gatherer.Clone(), this._dataStore, _dragManager);
                deckWindow.DeckClosedEvent += new EventHandler<DeckEventArgs>(Deck_Closed);
                deckWindow.DeckSavedEvent += new EventHandler<DeckEventArgs>(Deck_Saved);
                deckWindow.Show();
                _openDecks.Add(deckWindow);
            }
        }

        void Deck_Saved(object sender, DeckEventArgs e)
        {
            RefreshDecks();
        }

        void Deck_Closed(object sender, DeckEventArgs e)
        {
            DeckWindow deckWindow = _openDecks.SingleOrDefault(window => window.DeckName == e.DeckName);
            if (deckWindow != null)
            {
                _openDecks.Remove(deckWindow);
            }
        }

        private void ReportIssue_Click(object sender, System.Windows.RoutedEventArgs e)
        {
        	using (System.Diagnostics.Process process = new System.Diagnostics.Process())
            {
                process.StartInfo.FileName = "https://lapathy.fogbugz.com/default.asp?pg=pgPublicEdit";
                process.Start();
            }
        }

        private void Card_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            _dragManager.PreviewMouseLeftButtonDown((FrameworkElement)sender, e, false);
        }

        private void Card_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            _dragManager.PreviewMouseMove((FrameworkElement)sender, e, this);
        }            
    }
}
